#ifndef MARCHING_SQUARES_H
#define MARCHING_SQUARES_H

#include <Eigen/Dense>
#include <vector>
#include <map>
#include <deque>
#include <cmath>
#include <algorithm>

namespace EddyDetection {

// 线段结构体
struct LineSegment {
    Eigen::Vector2d start_point;
    Eigen::Vector2d end_point;
    int start_edge;  // 起始边编号
    int end_edge;    // 结束边编号
    int grid_i;      // 网格行索引
    int grid_j;      // 网格列索引
    
    LineSegment(const Eigen::Vector2d& start, const Eigen::Vector2d& end, 
                int start_e, int end_e, int i, int j)
        : start_point(start), end_point(end), start_edge(start_e), 
          end_edge(end_e), grid_i(i), grid_j(j) {}
};

class MarchingSquares {
public:
    // 构造函数
    MarchingSquares() = default;
    
    // 析构函数
    ~MarchingSquares() = default;

    // 从二值图像提取轮廓，返回有序的轮廓点序列
    // 输入: binary_grid - 二值图像 (lat为行, lon为列)
    //       lat - 纬度坐标向量
    //       lon - 经度坐标向量
    // 输出: 每个轮廓是一个有序排列的点序列，每个点为Eigen::Vector2d(lat, lon)
    std::vector<std::vector<Eigen::Vector2d>> extractContours(
        const Eigen::MatrixXi& binary_grid,
        const Eigen::VectorXd& lat,
        const Eigen::VectorXd& lon);

private:
    // 第一步：生成所有线段
    std::vector<LineSegment> generateLineSegments(
        const Eigen::MatrixXi& grid,
        const Eigen::VectorXd& lat,
        const Eigen::VectorXd& lon);

    // 第二步：组装线段成完整轮廓
    std::vector<std::deque<Eigen::Vector2d>> assembleContours(
        const std::vector<LineSegment>& segments);

    // 检查轮廓是否闭合
    bool isContourClosed(const std::deque<Eigen::Vector2d>& contour, double tolerance = 1e-6) const;

    // 第三步：输出有序轮廓点
    std::vector<std::vector<Eigen::Vector2d>> outputOrderedContours(
        const std::vector<std::deque<Eigen::Vector2d>>& contours);

    // 计算网格单元的状态 (0-15)
    int getCellState(int i, int j, const Eigen::MatrixXi& grid) const;

    // 获取边上的两个顶点坐标
    std::pair<Eigen::Vector2d, Eigen::Vector2d> getEdgeVertices(int edge, int i, int j,
        const Eigen::VectorXd& lat,
        const Eigen::VectorXd& lon) const;

    // 计算边的中点（简化版插值）
    Eigen::Vector2d getEdgeMidpoint(int edge, int i, int j,
        const Eigen::VectorXd& lat,
        const Eigen::VectorXd& lon) const;

    // 检查两个点是否足够接近（用于端点匹配）
    bool pointsMatch(const Eigen::Vector2d& p1, const Eigen::Vector2d& p2, double tolerance = 1e-6) const;
};

} // namespace EddyDetection

#endif // MARCHING_SQUARES_H
